home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / raytrace / rayshade / graphtal.lzh / Graphtal.Amiga / Interpreter.C < prev    next >
C/C++ Source or Header  |  1992-11-17  |  20KB  |  894 lines

  1. /*
  2.  * Interpreter.C - methods for turtle interpreter.
  3.  *
  4.  * Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
  5.  *                     University of Berne, Switzerland
  6.  * All rights reserved.
  7.  *
  8.  * This software may be freely copied, modified, and redistributed
  9.  * provided that this copyright notice is preserved on all copies.
  10.  *
  11.  * You may not distribute this software, in whole or in part, as part of
  12.  * any commercial product without the express consent of the authors.
  13.  *
  14.  * There is no warranty or other guarantee of fitness of this software
  15.  * for any purpose.  It is provided solely "as is".
  16.  *
  17.  */
  18.  
  19. #include "Interpreter.h"
  20. #include "Options.h"
  21. #include "Polygon.h"
  22. #include "Turtle.h"
  23. #include "DeviceDriver.h"
  24. #include "Module.h"
  25. #include "Hull.h"
  26. #include "boolean.h"
  27.  
  28. #define startBranchSymbol "["
  29. #define endBranchSymbol   "]"
  30.  
  31. #ifdef OLD_STYLE_CPP
  32.  InterpreterFunctions Interpreter::FuncTable[] = {
  33. #else
  34.  Interpreter::InterpreterFunctions Interpreter::FuncTable[] = {
  35. #endif
  36.  
  37.   {"F",               &Interpreter::forward},
  38.   {"wi",              &Interpreter::width},
  39.   {"G",               &Interpreter::go},
  40.   {"f",               &Interpreter::go},
  41.   {"pt",              &Interpreter::pitch},
  42.   {"&",               &Interpreter::pitch_negativ},
  43.   {"^",               &Interpreter::pitch},
  44.   {"ro",              &Interpreter::roll},
  45.   {"\\",              &Interpreter::roll_negativ},
  46.   {"/",               &Interpreter::roll},
  47.   {"tu",              &Interpreter::turn},
  48.   {"+",               &Interpreter::turn_negativ},
  49.   {"-",               &Interpreter::turn},
  50.   {"rv",              &Interpreter::rotate_vertical},
  51.   {"$",               &Interpreter::rotate_vertical},
  52.   {"|",               &Interpreter::reverse},
  53.   {startBranchSymbol, &Interpreter::push},
  54.   {endBranchSymbol,   &Interpreter::pop},
  55.   {"{",               &Interpreter::startPolygon},
  56.   {"sv",              &Interpreter::saveVertex},
  57.   {".",               &Interpreter::saveVertex},
  58.   {"}",               &Interpreter::endPolygon},
  59.   {"t",               &Interpreter::tropism},
  60.   {"we",              &Interpreter::weight},
  61.   {"co",              &Interpreter::color},
  62.   {"sm",              &Interpreter::beginMacro},
  63.   {"em",              &Interpreter::endMacro},
  64.   {"xm",              &Interpreter::executeMacro},
  65.   {"lib",             &Interpreter::libraryObject},
  66.   {"s",               &Interpreter::sphere},
  67.   {"tri",             &Interpreter::triangle},
  68.   {"poly",            &Interpreter::polygon},
  69.   {"ah",              &Interpreter::activateHull},
  70.   {"dh",              &Interpreter::deactivateHull},
  71.   {"cb",              &Interpreter::cutBranchWhenHit},
  72.   {"%",               &Interpreter::cutBranch},
  73.   {"texture",         &Interpreter::texture},
  74.   {"LastFunc",        NULL}
  75. };
  76.  
  77. FP* Interpreter::functable = NULL;
  78. Value Interpreter::turtleX;
  79. Value Interpreter::turtleY;
  80. Value Interpreter::turtleZ;
  81.  
  82. typedef Turtle* TurtlePtr;
  83. declareList(TurtleStack, TurtlePtr)
  84. implementList(TurtleStack, TurtlePtr)
  85.  
  86. //___________________________________________________________ Interpreter
  87.  
  88. Interpreter::Interpreter(DeviceDriver* device, Options* theOptions)
  89. : d(device), options(theOptions),
  90.   t(NULL), m(NULL), ml(NULL), currentModule(-1), saveTurtle(NULL), 
  91.   polyStack(new PolygonList(100)), turtleStack(new TurtleStack(100)),
  92.   definingMacro(FALSE), reflected(FALSE), deleteBranchWhenHit(FALSE)
  93. {
  94.  
  95.   /*
  96.    * Set up function table if not already done.
  97.    */
  98.   if (functable == NULL) {
  99.  
  100.     /*
  101.      * Add all the function names to global name space.
  102.      */
  103.     for (register int i=0; FuncTable[i].function != NULL; i++) 
  104.       FuncTable[i].index = Name::addname(FuncTable[i].name);
  105.  
  106.     functable = new FP[Name::namesCount()];
  107.  
  108.     /*
  109.      * Generate and initialize hash table for function pointers.
  110.      */
  111.     for (i=0; i<Name::namesCount(); i++)
  112.       functable[i] = NULL;
  113.     for (i=0; FuncTable[i].function != NULL; i++)
  114.       functable[FuncTable[i].index] = FuncTable[i].function;
  115.   }
  116.  
  117.   /*
  118.    * Set up analytic tropism functions and hulls.
  119.    */
  120.   tropismX = options->tropismX; 
  121.   tropismY = options->tropismY; 
  122.   tropismZ = options->tropismZ; 
  123.   tropismFunction = 
  124.     (tropismX != NULL) || (tropismY != NULL) || (tropismZ != NULL);
  125.   tropismWeight = options->weight;
  126.   weightFunction = (tropismWeight != NULL);
  127.   h = options->hulls;
  128. }
  129.  
  130. Interpreter::~Interpreter()
  131. {
  132.   delete polyStack;
  133.   delete turtleStack;
  134. }
  135.  
  136. /*
  137.  * Interpret the module string modules using the given dive driver.
  138.  */
  139.  
  140. void Interpreter::interpret(ModuleList* modules)
  141. {
  142.   t = new Turtle; 
  143.   ml = modules;
  144.  
  145.   /*
  146.    * Start interpretation of module string ml.
  147.    */
  148.   if (!options->quiet)
  149.     cerr << "Start of Interpretation ...\n\n";
  150.  
  151.   d->begin();
  152.  
  153.   /*
  154.    * For each module lookup corresponding interpreter function, call it
  155.    * if not NULL.
  156.    */
  157.   for (currentModule = 0; currentModule < ml->count(); currentModule++) {
  158.     m = ml->item(currentModule);
  159.     if (functable[ml->item(currentModule)->name().index()] != NULL) {
  160.       FP currentFunc = functable[ml->item(currentModule)->name().index()];
  161.       (this->*currentFunc)();
  162.     }
  163.       
  164.     if (options->deleteModules)
  165.       delete ml->item(currentModule);
  166.  
  167.     /*
  168.      * If we hit any hull primitive and deleteBranchWhenHit option is
  169.      * set, ignore all modules up to the next end branch command ("]").
  170.      * Note that we have to skip all the subbranches also.
  171.      */
  172.     if (deleteBranchWhenHit && reflected) {
  173.       reflected = FALSE; // reset
  174.       cutBranch();
  175.     }
  176.   }
  177.  
  178.   flush();
  179.  
  180.   /*
  181.    * Visualize the defined hulls.
  182.    */
  183.   if (options->showHulls) {
  184.     PolygonList* polys;
  185.  
  186.     Color hullColor("HullColor");
  187.     d->color(hullColor);
  188.     for (HullSymtab_Iterator hullItr(*h); hullItr.more(); hullItr.next()) {
  189.       polys = hullItr.cur_value()->convertToPolygonList(t->bbox());
  190.       for (register long i=0; i<polys->count(); i++)
  191.     d->polygon(polys->item(i));
  192.       delete polys;
  193.     } 
  194.   }
  195.  
  196.   if (options->verbose) {
  197.     cerr << "BoundingBox: " << t->bbox() << "\n\n";
  198.     cerr << "intersection tests: " 
  199.      << GeoObject::getIntersectionTests() <<"\n"
  200.          << "intersection hits:  " 
  201.      << GeoObject::getIntersections() << "\n\n";
  202.   }
  203.  
  204.   d->end(t->bbox());
  205.  
  206.   delete t;
  207. }
  208.  
  209. //___________________________________________________________ interpreter functions
  210.  
  211. /*
  212.  * Flush checks if there is a segment in the pipe which has't been draw yet
  213.  * (lastWidth > 0) and draws it in that case.
  214.  */
  215.  
  216. void Interpreter::flush()
  217. {
  218.   /*
  219.    * A segment left in the pipe?
  220.    */
  221.   if (t->getLastWidth() > 0) {
  222.     if (tropismFunction || weightFunction)
  223.       computeTropism();
  224.  
  225.     d->color(t->getLastColor());
  226.     d->texture(t->getLastTexture());
  227.  
  228.     if (equal(t->getLastWidth(), t->getWidth()))
  229.       d->cylinder(t->lastPos(), t->pos(), t->getWidth());
  230.     else if (!options->coneSpheres)
  231.       d->cone(t->lastPos(), t->getLastWidth(), t->pos(), t->getWidth());
  232.     else
  233.       createConeBetweenSpheres(t->lastPos(), t->getLastWidth(), 
  234.                    t->pos(), t->getWidth());      
  235.     if (options->coneSpheres)
  236.       d->sphere(t->pos(), t->getWidth());
  237.   }
  238.   t->setLastWidth(-1); // no segments left in the pipe
  239. }
  240.  
  241. /*
  242.  * Go forward and draw a line.
  243.  * lastWidth < 0: no move has been previously done
  244.  */
  245.  
  246. void Interpreter::forward()
  247.   real step;
  248.  
  249.   /*
  250.    * Is there an argument for the move?
  251.    */
  252.   if (m->argCount() <= 0 || !m->arg(0)->toReal(step)) 
  253.     step = options->defaultForward;
  254.  
  255.   /*
  256.    * Do we really have to move?
  257.    */
  258.   if (equal(step, 0)) {
  259.     Error(ERR_ADVISE, "Interpreter::forward with argument 0");
  260.     return;
  261.   }
  262.  
  263.   /*
  264.    * Recompute tropism and weight functions if any present.
  265.    */
  266.   if (tropismFunction || weightFunction)
  267.     computeTropism();
  268.  
  269.   if (t->getLastWidth() > 0) {
  270.     d->color(t->getLastColor());
  271.     d->texture(t->getLastTexture());
  272.   }
  273.  
  274.   real lastWidth    = t->getLastWidth();
  275.   real currentWidth = t->getWidth();
  276.   Vector lastPos    = t->lastPos();
  277.   Vector currentPos = t->pos();
  278.   reflected = t->forward(step);
  279.   Vector newPos     = t->pos();
  280.  
  281.   /*
  282.    * Regular line segment or cone spheres?
  283.    */
  284.   if (lastWidth > 0) {
  285.     if (equal(lastWidth, currentWidth))
  286.       d->cylinder(lastPos, currentPos, lastWidth);
  287.     else if (!options->coneSpheres)
  288.       d->cone(lastPos, lastWidth, currentPos, currentWidth);    
  289.     else 
  290.       createConeBetweenSpheres(lastPos, lastWidth, currentPos, currentWidth);
  291.     
  292.    /*
  293.     * Add sphere when there's an angle between the segments.
  294.     */
  295.     if (options->coneSpheres && !((lastPos-currentPos)*(currentPos-newPos)).zero())
  296.       d->sphere(currentPos, currentWidth);
  297.   }
  298. }
  299.  
  300. /*
  301.  * Go forward without drawing a line.
  302.  */
  303.  
  304. void Interpreter::go()
  305.   real step;
  306.  
  307.   flush();
  308.   if (tropismFunction || weightFunction)
  309.     computeTropism();
  310.  
  311.   if (m->argCount()>0 && m->arg(0)->toReal(step))
  312.     reflected = t->forward(step);
  313.   else
  314.     reflected = t->forward(options->defaultForward);
  315.  
  316.   /*
  317.    * There's no segment in the pipe left.
  318.    */
  319.   t->setLastWidth(-1);
  320. }
  321.  
  322. /*
  323.  * Set line width.
  324.  */
  325.  
  326. void Interpreter::width()
  327. {
  328.   real width;
  329.   if (m->argCount()>0 && m->arg(0)->toReal(width) && width>0) 
  330.     t->setWidth(width);
  331. }
  332.  
  333. /*
  334.  * Pitch turtle in positive direction.
  335.  */
  336.  
  337. void Interpreter::pitch()
  338.   real a;
  339.   if (m->argCount()>0 && m->arg(0)->toReal(a)) 
  340.     t->pitch(dtor(a));
  341.   else
  342.     t->pitch(options->defaultPitch);
  343. }
  344.  
  345. /*
  346.  * Pitch turtle in negative direction.
  347.  */
  348.  
  349. void Interpreter::pitch_negativ()
  350.   real a;
  351.   if (m->argCount()>0 && m->arg(0)->toReal(a)) 
  352.     t->pitch(-dtor(a));
  353.   else
  354.     t->pitch(-options->defaultPitch);
  355. }
  356.  
  357. /*
  358.  * Turn turtle in positive direction.
  359.  */
  360.  
  361. void Interpreter::turn()
  362.   real a;
  363.   if (m->argCount()>0 && m->arg(0)->toReal(a)) 
  364.     t->turn(dtor(a));
  365.   else
  366.     t->turn(options->defaultTurn);
  367. }
  368.  
  369. /*
  370.  * Turn turtle in negative direction.
  371.  */
  372.  
  373. void Interpreter::turn_negativ()
  374.   real a;
  375.   if (m->argCount()>0 && m->arg(0)->toReal(a)) 
  376.     t->turn(-dtor(a));
  377.   else
  378.     t->turn(-options->defaultTurn);
  379. }
  380.  
  381. /*
  382.  * Roll turtle in positive direction.
  383.  */
  384.  
  385. void Interpreter::roll()
  386.   real a;
  387.   if (m->argCount()>0 && m->arg(0)->toReal(a)) 
  388.     t->roll(dtor(a));
  389.   else
  390.     t->roll(options->defaultRoll);
  391. }
  392.  
  393. /*
  394.  * Roll turtle in negative direction.
  395.  */
  396.  
  397. void Interpreter::roll_negativ()
  398.   real a;
  399.   if (m->argCount()>0 && m->arg(0)->toReal(a)) 
  400.     t->roll(-dtor(a));
  401.   else
  402.     t->roll(-options->defaultRoll);
  403. }
  404.  
  405. /*
  406.  * Align turtle vertical.
  407.  */
  408.  
  409. void Interpreter::rotate_vertical()
  410. {
  411.   t->rotate_vertical();
  412. }
  413.  
  414. /*
  415.  * Reverse heading of the turtle.
  416.  */
  417.  
  418. void Interpreter::reverse()
  419. {
  420.   t->reverse();
  421. }
  422.  
  423. /*
  424.  * Save current turtle state on the stack.
  425.  */
  426.  
  427. void Interpreter::push()
  428. {
  429.   turtleStack->prepend(t);
  430.   t = new Turtle(*t);
  431.   t->setLastWidth(-1);
  432. }
  433.  
  434. /*
  435.  * Restore turtle state from stack.
  436.  */
  437.  
  438. void Interpreter::pop()
  439. {
  440.   flush();
  441.  
  442.   if (turtleStack->count() > 0) {
  443.     turtleStack->item(0)->expandBBoxBy(t->bbox());
  444.     delete t;
  445.     t = turtleStack->item(0);
  446.     turtleStack->remove(0);
  447.   }
  448.   else 
  449.     Error(ERR_WARN, "Interpreter::pop stack is empty");
  450. }
  451.  
  452. /*
  453.  * Start a new polygon.
  454.  */
  455.  
  456. void Interpreter::startPolygon()
  457. {
  458.   polyStack->prepend(new Polygon);
  459. }
  460.  
  461. /*
  462.  * Add vertex to current polygon.
  463.  */
  464.  
  465. void Interpreter::saveVertex()
  466. {
  467.   if (polyStack->count() > 0)
  468.     polyStack->item(0)->addVertex(t->pos());
  469.   else
  470.     Error(ERR_WARN, "Interpreter::saveVertex polygon stack is empty");
  471. }
  472.  
  473. /*
  474.  * End of polygon definition.
  475.  */
  476.  
  477. void Interpreter::endPolygon()
  478. {
  479.   if (polyStack->count() <= 0) {
  480.     Error(ERR_WARN, "Interpreter::endPolygon polygon stack is empty");
  481.     return;
  482.   }
  483.  
  484.   Polygon* p = polyStack->item(0);
  485.  
  486.   if (p->numVertices() <= 0) {
  487.     Error(ERR_WARN, "Interpreter::endPolygon no vertex in polygon");
  488.     delete p;
  489.     polyStack->remove(0);
  490.     return;
  491.   }
  492.   
  493.   /*
  494.    * Start and endpoint should not be the same.
  495.    */
  496.   if (p->numVertices()>1 && p->vertex(0) == p->vertex(p->numVertices()-1))
  497.     p->removeVertex(p->numVertices()-1);
  498.  
  499.   /* 
  500.    * Set color and texture.
  501.    */
  502.   d->color(t->getColor());
  503.   d->texture(t->getTexture());
  504.  
  505.   d->polygon(p);
  506.  
  507.   polyStack->remove(0);
  508. }
  509.  
  510. /*
  511.  * Set tropism vector.
  512.  */
  513.  
  514. void Interpreter::tropism()
  515. {
  516.   real x, y, z, w;
  517.   if (m->argCount() >= 3  &&  
  518.       m->arg(0)->toReal(x) && m->arg(1)->toReal(y) && m->arg(2)->toReal(z)) {
  519.     t->setTropism(x,y,z);
  520.  
  521.     if (m->argCount() >= 4 && m->arg(3)->toReal(w))
  522.       t->setWeight(w);
  523.   }
  524. }
  525.  
  526. /*
  527.  * Set weight for tropism calculations.
  528.  */
  529.  
  530. void Interpreter::weight()
  531. {
  532.   real w;
  533.   if (m->argCount()>0 && m->arg(0)->toReal(w)) 
  534.     t->setWeight(w);
  535. }
  536.  
  537. /*
  538.  * Set color.
  539.  */
  540.  
  541. void Interpreter::color()
  542. {
  543.   if (m->argCount()>0) {
  544.     Color c(m->arg(0)->toString());
  545.     t->setColor(c);
  546.   }
  547. }
  548.  
  549. /* 
  550.  * Start macro definition.
  551.  */
  552.  
  553. void Interpreter::beginMacro()
  554. {
  555.   if (definingMacro) 
  556.     Error(ERR_PANIC, "Interpreter::beginMacro nested macro definition");
  557.   
  558.   if (m->argCount() <= 0) 
  559.     Error(ERR_PANIC, "Interpreter::beginMacro macro definition without a name");
  560.  
  561.   rcString macroName(m->arg(0)->toString());
  562.  
  563.   if (!d->addMacroName(macroName))
  564.     Error(ERR_PANIC, "Interpreter::beginMacro macro \"" 
  565.                      + macroName + "\" already defined");
  566.   
  567.   saveTurtle = t; 
  568.   t = new Turtle; 
  569.   definingMacro = TRUE;
  570.   d->beginMacro(macroName);
  571. }
  572.  
  573. /*
  574.  * End of macro definition.
  575.  */
  576.  
  577. void Interpreter::endMacro()
  578. {
  579.   if (definingMacro == FALSE) {
  580.     Error(ERR_WARN, "Interpreter::endMacro missing begin macro");
  581.     return;
  582.   }
  583.  
  584.   flush();
  585.   d->endMacro();
  586.   delete t;
  587.   t = saveTurtle; saveTurtle = NULL;
  588.   definingMacro = FALSE;
  589. }
  590.  
  591. /*
  592.  * Execute a already defined macro.
  593.  */
  594.  
  595. void Interpreter::executeMacro()
  596. {
  597.   if (m->argCount() <= 0) {
  598.     Error(ERR_WARN, "Interpreter::executeMacro macro without a name");
  599.     return;
  600.   }
  601.  
  602.   TransMatrix tmat;
  603.   real scale;
  604.  
  605.   tmat(0,0) = t->vecU()[0]; tmat(0,1) = t->vecU()[1]; tmat(0,2) = t->vecU()[2]; 
  606.   tmat(1,0) = t->vecL()[0]; tmat(1,1) = t->vecL()[1]; tmat(1,2) = t->vecL()[2]; 
  607.   tmat(2,0) = t->vecH()[0]; tmat(2,1) = t->vecH()[1]; tmat(2,2) = t->vecH()[2]; 
  608.  
  609.   if (m->argCount()>1 && m->arg(1)->toReal(scale) && !equal(scale, 1))
  610.     tmat.scale(scale, scale, scale);
  611.   tmat.translate(t->pos());
  612.  
  613.   d->executeMacro(m->arg(0)->toString(), tmat);
  614. }
  615.  
  616. /*
  617.  * Include a predefined object.
  618.  */
  619.  
  620. void Interpreter::libraryObject()
  621. {
  622.   if (m->argCount() <= 0) {
  623.     Error(ERR_WARN, "Interpreter::libraryObject object without a name");
  624.     return;
  625.   }
  626.  
  627.   TransMatrix tmat;
  628.   real scale;
  629.  
  630.   rcString libName(m->arg(0)->toString());
  631.  
  632.   d->addLibraryObjectName(libName);
  633.  
  634.   tmat(0,0) = t->vecU()[0]; tmat(0,1) = t->vecU()[1]; tmat(0,2) = t->vecU()[2]; 
  635.   tmat(1,0) = t->vecL()[0]; tmat(1,1) = t->vecL()[1]; tmat(1,2) = t->vecL()[2]; 
  636.   tmat(2,0) = t->vecH()[0]; tmat(2,1) = t->vecH()[1]; tmat(2,2) = t->vecH()[2]; 
  637.  
  638.   if (m->argCount()>1 && m->arg(1)->toReal(scale) && !equal(scale, 1))
  639.     tmat.scale(scale, scale, scale);
  640.   tmat.translate(t->pos());
  641.  
  642.   d->libraryObject(libName, tmat);
  643. }
  644.  
  645. /*
  646.  * Generate sphere at turtle position with given radius.
  647.  */
  648.  
  649. void Interpreter::sphere()
  650. {
  651.   real r;
  652.  
  653.   /* 
  654.    * Set color and texture.
  655.    */
  656.   d->color(t->getColor());
  657.   d->texture(t->getTexture());
  658.  
  659.   if (m->argCount()>0 && m->arg(0)->toReal(r)) 
  660.     d->sphere(t->pos(), r);
  661.   else
  662.     d->sphere(t->pos(), 1);
  663. }
  664.  
  665. /*
  666.  * Generate triangle with given vertices.
  667.  */
  668.  
  669. void Interpreter::triangle()
  670. {
  671.   if (m->argCount() < 9)
  672.     return;
  673.  
  674.   real coords[9];
  675.   for (register int i=0; i<9; i++)
  676.     if (!m->arg(i)->toReal(coords[i]))
  677.       return;
  678.  
  679.   Vector p1(coords[0], coords[1], coords[2]); 
  680.   Vector p2(coords[3], coords[4], coords[5]); 
  681.   Vector p3(coords[6], coords[7], coords[8]); 
  682.  
  683.   BoundingBox tmpBBox;
  684.   tmpBBox.expand(p1);
  685.   tmpBBox.expand(p2);
  686.   tmpBBox.expand(p3);
  687.   t->expandBBoxBy(tmpBBox);
  688.  
  689.   /* 
  690.    * Set color and texture.
  691.    */
  692.   d->color(t->getColor());
  693.   d->texture(t->getTexture());
  694.  
  695.   d->polygon(new Polygon(p1, p2, p3));
  696. }
  697.  
  698. /*
  699.  * Generate polygon with given vertices.
  700.  */
  701.  
  702. void Interpreter::polygon()
  703. {
  704.   if (m->argCount() < 9)
  705.     return;
  706.  
  707.   real x, y, z;
  708.   Polygon* p = new Polygon(3);
  709.   BoundingBox tmpBBox;
  710.  
  711.   for (register int i=0; i<m->argCount()-2; i+=3) {
  712.     if (m->arg(i)->toReal(x)   && 
  713.     m->arg(i+1)->toReal(y) && 
  714.     m->arg(i+2)->toReal(z)) 
  715.       {
  716.     p->addVertex(Vector(x,y,z));
  717.     tmpBBox.expand(Vector(x,y,z));
  718.       }
  719.   }
  720.  
  721.   if (p->numVertices() > 2) {
  722.  
  723.     /* 
  724.      * Set color and texture.
  725.      */
  726.     d->color(t->getColor());
  727.     d->texture(t->getTexture());
  728.  
  729.     d->polygon(p);
  730.     t->expandBBoxBy(tmpBBox);
  731.   }
  732.   else
  733.     delete p;
  734. }
  735.  
  736. /*
  737.  * Activate a hull. Turtle will move with respect to the primitives
  738.  * of the hull.
  739.  */
  740.  
  741. void Interpreter::activateHull()
  742. {
  743.   if (m->argCount()<=0) {
  744.     Error(ERR_WARN, "Interpreter::activateHull no hull name");
  745.     return;
  746.   }
  747.  
  748.   rcString hullName(m->arg(0)->toString());
  749.  
  750.   Hull* hull;
  751.   if (!h->lookup(hullName, hull)) {
  752.     Error(ERR_WARN, "Interpreter::activateHull unknown hull " + hullName);
  753.     return;
  754.   }
  755.   real reflectanceFactor = 1;
  756.   if (m->argCount()>1)
  757.     m->arg(1)->toReal(reflectanceFactor);
  758.   
  759.   t->setHull(hull, reflectanceFactor);
  760. }
  761.  
  762. void Interpreter::deactivateHull()
  763. {
  764.   t->unsetHull();
  765. }
  766.  
  767. /*
  768.  * Set/Unset of delete branch when conflict with current hull.
  769.  */
  770.  
  771. void Interpreter::cutBranchWhenHit()
  772. {
  773.   real flag = TRUE;
  774.   if (m->argCount() > 0)
  775.     m->arg(0)->toReal(flag);
  776.     
  777.   if ((int)flag) {
  778.     deleteBranchWhenHit = TRUE;
  779.     t->setStopOnHit();
  780.   }
  781.   else {
  782.     deleteBranchWhenHit = FALSE;
  783.     t->unsetStopOnHit();
  784.   }
  785. }
  786.  
  787. /*
  788.  * Ignore all the modules until we find a end branch symbol (ignore
  789.  * subbranches also).
  790.  */
  791.  
  792. void Interpreter::cutBranch()
  793. {
  794.   static Name startBranch(startBranchSymbol);
  795.   static Name endBranch(endBranchSymbol);
  796.   int nested = 0;
  797.  
  798.   /*
  799.    * Ignore all modules up to the next end branch command ("]").
  800.    * Note that we have to skip all the subbranches also.
  801.    */
  802.   while (++currentModule < ml->count()) {
  803.     if (ml->item(currentModule)->name() == startBranch)
  804.       nested++;
  805.     else if (ml->item(currentModule)->name() == endBranch) {
  806.       if (nested-- == 0) {
  807.     currentModule--; 
  808.     break;
  809.       }
  810.     }
  811.     if (options->deleteModules)
  812.       delete ml->item(currentModule);
  813.   }
  814. }
  815.  
  816. /*
  817.  * Define texture for the following primitives.
  818.  */
  819. void Interpreter::texture()
  820. {
  821.   if (m->argCount()>0) {
  822.     rcString theTexture(m->arg(0)->toString());
  823.     t->setTexture(theTexture);
  824.   }
  825.   else
  826.     t->setTexture(""); // disable textures
  827. }
  828.  
  829. /*
  830.  * Generate a cone between two given spheres. 
  831.  */
  832.  
  833. void Interpreter::createConeBetweenSpheres(const Vector& p1, real r1, 
  834.                             const Vector& p2, real r2)
  835. {
  836.   real a = r1-r2;
  837.   real r = r1;
  838.   real c = p1.distance(p2);
  839.   int secondIsLarger = FALSE;
  840.  
  841.   if (c<r1 || c<r2) {
  842.     Error(ERR_ADVISE, rcString("Interpreter::createConeBetweenSpheres\n") + 
  843.                       "\tdistance between spheres is too small -> can't create cone\n");
  844.     return;
  845.   }
  846.     
  847.   if (a < 0) {
  848.     r = r2;
  849.     a = -a;
  850.     secondIsLarger = TRUE;
  851.   }
  852.   
  853.   real p  = a*a/c;
  854.   real ps = p*r/a;
  855.  
  856.   real h  = sqrt(p*(c-p));
  857.   real hs = h*r/a;
  858.  
  859.   Vector dir = p2 - p1;
  860.  
  861.   if (secondIsLarger)
  862.     d->cone(p1-dir*((ps-p)/c), hs-h, p2-dir*(ps/c), hs);
  863.   else
  864.     d->cone(p1+dir*(ps/c), hs, p2+dir*((ps-p)/c), hs-h);
  865. }
  866.  
  867. /*
  868.  * If tropism vector depends on turtle position, we recompute the
  869.  * tropism vector after each move.
  870.  */
  871.  
  872. void Interpreter::computeTropism()
  873. {
  874.   turtleX = t->pos()[0];
  875.   turtleY = t->pos()[1];
  876.   turtleZ = t->pos()[2];
  877.  
  878.   if (tropismFunction)
  879.     t->setTropism(tropismX->evaluate(),
  880.           tropismY->evaluate(),
  881.           tropismZ->evaluate());  
  882.  
  883.   if (weightFunction)
  884.     t->setWeight(tropismWeight->evaluate());
  885. }
  886.